/**************************************************************************(C)*
 *
 *  This file is part of the GreenHills project
 *  Copyright (C) 2009  Tieto Corporation
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  Not for commmercial use. Only with Tieto permission.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************(C)*/

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "logindialog.h"
#include "gpsinfowidget.h"
#include "nmeapreviewwidget.h"
#include "roomitemswidget.h"
#include "settingsdialog.h"
#include "addwaypointdialog.h"
#include "targetnavigationwidget.h"
#include "mapwiev.h"

#include "util/serialport.h"
#include "util/lineterminal.h"
#include "util/timerbox.h"
#include "util/conversion.h"
#include "gps/nmeaparser.h"
#include "gps/emulator.h"
#include "gps/gps.h"
#include "core/waypoint.h"

#include "client/core/client.h"
#include "client/core/room.h"
#include "client/core/target.h"
#include "client/mva/roommodel.h"

#include <QtCore/QSettings>
#include <QtGui/QMessageBox>
#include <QtGui/QInputDialog>

#define DEFAULT_HOST_NAME "localhost"

using namespace greenhills::client;
using namespace greenhills::util;
using namespace greenhills::gps;

CMainWindow::CMainWindow(CSerialPort *serialPort,
        CLineTerminal *lineTerminal, CNMEAParser *nmeaParser,
        core::CClient &pClient, QWidget *pParent)
    :QMainWindow(pParent), mUi(new Ui::CMainWindow), mSerialPort(serialPort),
    mLineTerminal(lineTerminal), mNmeaParser(nmeaParser), mClient(pClient),
    mRoomView(0)
{
    mUi->setupUi(this);

    QObject::connect(&mClient, SIGNAL(roomJoined()),
        this, SLOT(onRoomJoined()));
    QObject::connect(&mClient, SIGNAL(roomLeft()),
        this, SLOT(onRoomLeft()));
    QObject::connect(&mClient, SIGNAL(userLoggedIn()),
        this, SLOT(onUserLoggedIn()));
    QObject::connect(&mClient, SIGNAL(userLoggedOut()),
        this, SLOT(onUserLoggedOut()));

    mGps = new CGPS(nmeaParser, this);

    mGpsEmulator = new CEmulator(
            CGPSPosition(
                CGPSCoordinate(17*CGPSCoordinate::COORD_1_DEGREE),
                CGPSCoordinate(50*CGPSCoordinate::COORD_1_DEGREE)),
            5000, 3000, 0, this);
//    QObject::connect(
//        mGpsEmulator, SIGNAL(GPGGAreceived(
//        QTime,greenhills::gps::CGPSPosition,greenhills::gps::CGPSFix,
//        int,float,float,float,float,int)),
//        mGps, SLOT(onGPGGAreceived(
//        QTime,greenhills::gps::CGPSPosition,greenhills::gps::CGPSFix,
//        int,float,float,float,float,int)));
//    QObject::connect(
//        mGpsEmulator,SIGNAL(GPVTGreceived(float,float,float,float)),
//        mGps,SLOT(onGPVTGreceived(float,float,float,float)));

    QObject::connect(
        mGpsEmulator, SIGNAL(GPGGAreceived(
        QTime,greenhills::gps::CGPSPosition,greenhills::gps::CGPSFix,
        int,float,float,float,float,int)),
        mNmeaParser, SIGNAL(GPGGAreceived(
        QTime,greenhills::gps::CGPSPosition,greenhills::gps::CGPSFix,
        int,float,float,float,float,int)));
    QObject::connect(
        mGpsEmulator, SIGNAL(GPVTGreceived(float,float,float,float)),
        mNmeaParser, SIGNAL(GPVTGreceived(float,float,float,float)));

    mUi->tabWidget->clear();

    mGpsInfoWidget = new CGPSInfoWidget(mGps, this);
    mUi->tabWidget->addTab(mGpsInfoWidget,"GPS Info");

    mNmeaPreviewWidget = new CNMEAPreviewWidget(mLineTerminal, this);
    mUi->tabWidget->addTab(mNmeaPreviewWidget,"NMEA");

    mTargetNavigationWidget = new CTargetNavigationWidget(mGps, this);
    mUi->tabWidget->addTab(mTargetNavigationWidget,"Navigation");

    mRoomItemsWidget = new CRoomItemsWidget(mClient, this);
    mUi->tabWidget->addTab(mRoomItemsWidget,"Room");

    mMapWiev = new CMapWiev(
    "ABQIAAAAehra_sQ1GfzD2bMT5ULq6BRNBWK4B2fFl05XeGjcTIxEL6jNCRSsrsdYAzCqrfURXnfqP9dzvWtGEA",
    this);
    mUi->tabWidget->addTab(mMapWiev,"Map");

//    CMapView *mMapView = new CMapView();
//    int mapIdx = mUi->tabWidget->addTab(mMapView,"Map");
//    mUi->tabWidget->setCurrentIndex(mapIdx);
}

CMainWindow::~CMainWindow()
{
    delete mUi;
}

void CMainWindow::on_actionLogin_triggered()
{
    QSettings settings("Tieto", "GreenHills", this);
    settings.beginGroup("server");
    QString host = settings.value("host", DEFAULT_HOST_NAME).toString();
    //settings.setValue("host", host);

    CLoginDialog dlg(this, mClient.userName().c_str());
    if (dlg.exec() != QDialog::Accepted)
        return;

    if (!mClient.connect(host))
    {
        QMessageBox::warning(0, tr("Connection Error"),
                tr("Connection with server has not been established"));
        return;
    }

    if (!mClient.login(dlg.userName(),dlg.password()))
    {
        QMessageBox::warning(0, tr("Login Error"),
                tr("Login failed. Check your username and password"));

        mClient.disconnect();
        return;
    }
}

void CMainWindow::on_actionLogout_triggered()
{
    mClient.logout();
    mClient.disconnect();
}

void CMainWindow::on_actionCreate_triggered()
{
    if (!mClient.createRoom("Default", 0, DEFAULT_PASSWORD))
    {
        QMessageBox::warning(0, tr("Create Room Error"),
                tr("Create room failed."));
    }
}

void CMainWindow::on_actionJoin_triggered()
{
    bool ok;
    QString password = QInputDialog::getText(this, tr("Join room"),
        tr("Enter room password, please:"), QLineEdit::Password, "", &ok);
    if (!ok)
        return;

    if (!mClient.joinRoom(DEFAULT_ROOM_ID, password))
    {
        QMessageBox::warning(0, tr("Join Room Error"),
                tr("Join room failed."));
        return;
    }

    if (!mClient.addLocalUser())
    {
        QMessageBox::warning(0, tr("Add Local User Error"),
                tr("Add Local User failed."));
        return;
    }

}

void CMainWindow::on_actionLeave_triggered()
{
    if (!mClient.leaveRoom())
    {
        QMessageBox::warning(0, tr("Leave Room Error"),
                tr("Leave room failed."));
        return;
    }
}

void CMainWindow::on_actionGpsConnect_triggered()
{
    QSettings settings("Tieto", "GreenHills", this);
    settings.beginGroup("gps");
    QString device = settings.value("device", "").toString();
    //settings.setValue("device", device);

    //if (mSerialPort->open("/dev/rfcomm1", B4800))
    //if (mSerialPort->open("\\\\.\\COM4", B4800))
    if (!mSerialPort->open(device.toAscii().data()))
        QMessageBox::warning(0, tr("Connect GPS"),
                tr("Attempt to open GPS connection failed."));
}

void CMainWindow::on_actionGpsDisconnect_triggered()
{
    if (!mSerialPort->close())
        QMessageBox::warning(0, tr("Disconnect GPS"),
                tr("Attempt to close GPS connection failed."));
}

void CMainWindow::on_actionSettings_triggered()
{
    CSettingsDialog dlg(this);
    dlg.exec();
}

void CMainWindow::on_actionEmulatorStart_triggered()
{
    mGpsEmulator->start();
}

void CMainWindow::on_actionEmulatorStop_triggered()
{
    mGpsEmulator->stop();
}

void CMainWindow::on_actionAddWaypoint_triggered()
{
    using namespace greenhills::core;

    CAddWaypointDialog dlg("Waypoint", mGps->position(), this);
    if (dlg.exec() != QDialog::Accepted)
        return;

    greenhills::core::IRoomItem *item =
            mClient.addItem(dlg.name(), CItemType::itWaypoint);

    greenhills::core::CWaypoint *waypoint =
            dynamic_cast<greenhills::core::CWaypoint*>(item);
    Q_ASSERT(waypoint != 0);

    waypoint->setPosition(dlg.position());
    waypoint->setTimeStamp(qtime2sec(QTime::currentTime()));
    mClient.updateItem(waypoint);
}

void CMainWindow::on_actionNavigateToTarget_triggered()
{
    using namespace greenhills::core;

    CAddWaypointDialog dlg("Target", client::core::CTarget::position(), this);
    if (dlg.exec() != QDialog::Accepted)
        return;

    client::core::CTarget::setPosition(dlg.position());
}

void CMainWindow::on_actionNavigateToCurrentPosition_triggered()
{
    if (!mGps->fix().isValid())
        QMessageBox::warning(0, tr("Invalid GPS Fix"),
                tr("Action is not allowed. GPS Fix is not valid."));

    client::core::CTarget::setPosition(mGps->position());
}

void CMainWindow::on_actionNavigationCancel_triggered()
{
    client::core::CTarget::clear();
}


void CMainWindow::onRoomJoined()
{
    mUi->actionAddWaypoint->setEnabled(true);
    mUi->actionLeave->setEnabled(true);

    mUi->actionJoin->setEnabled(false);
}

void CMainWindow::onRoomLeft()
{
    mUi->actionJoin->setEnabled(true);

    mUi->actionAddWaypoint->setEnabled(false);
    mUi->actionLeave->setEnabled(false);
}

void CMainWindow::onUserLoggedIn()
{
    mUi->actionCreate->setEnabled(true);
    mUi->actionJoin->setEnabled(true);
    mUi->actionLogout->setEnabled(true);
    mUi->actionLogin->setEnabled(false);
}

void CMainWindow::onUserLoggedOut()
{
    mUi->actionCreate->setEnabled(false);
    mUi->actionJoin->setEnabled(false);
    mUi->actionLogout->setEnabled(false);

    mUi->actionLogin->setEnabled(true);
}

